package com.yxw.live_vod_boot.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yxw.live_vod_boot.dto.YxLiveCostAddDTO;
import com.yxw.live_vod_boot.dto.YxVideoCoinAddDTO;
import com.yxw.live_vod_boot.dto.YxVideoCoinQueryDTO;
import com.yxw.live_vod_boot.entity.*;
import com.yxw.live_vod_boot.mapper.*;
import com.yxw.live_vod_boot.service.VideoCoinService;
import com.yxw.live_vod_boot.utils.AssertUtil;
import com.yxw.live_vod_boot.utils.PageUtils;
import com.yxw.live_vod_boot.vo.YxVideoCoinVO;
import com.yxw.live_vod_facade.dto.VideoCoinQueryDTO;
import com.yxw.yxnet_cd_center.common.constant.CommonConstant;
import com.yxw.yxnet_cd_center.common.dto.PageVO;
import com.yxw.yxnet_cd_center.common.enums.ErrorCodeEnum;
import com.yxw.yxnet_cd_center.common.exception.BaseException;
import com.yxw.yxnet_cd_center.common.utils.BaseDateTime;
import com.yxw.yxnet_cd_center.common.utils.IdWorkerUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 视频币明细
 * @author xiexuxin
 * @date 2023-11-17
 */
@Slf4j
@Service
public class VideoCoinServiceImpl extends ServiceImpl<VideoCoinMapper, YxVideoCoinEntity> implements VideoCoinService {

    @Autowired
    private VideoCoinMapper videoCoinMapper;

    @Autowired
    private VideoCoinExchangeMapper videoCoinExchangeMapper;

    @Autowired
    private YxLiveCostMapper liveCostMapper;

    @Autowired
    private ShopMapper shopMapper;

    @Autowired
    private YxLiveShopPunishMapper liveShopPunishMapper;

    @Autowired
    private YxLiveAddressMapper liveAddressMapper;

    /**
     * 添加视频币明细
     * @param videoCoinAddDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addVideoCoin(YxVideoCoinAddDTO videoCoinAddDTO) {
        YxVideoCoinEntity videoCoinEntity = new YxVideoCoinEntity();
        BeanUtil.copyProperties(videoCoinAddDTO, videoCoinEntity);
        // 如果类型为支出
        if (0 == videoCoinAddDTO.getType()) {
            handleExpendType(videoCoinAddDTO, videoCoinEntity);
        }
        // 如果类型为兑换
        if (1 == videoCoinAddDTO.getType()) {
            handleRechargeType(videoCoinAddDTO, videoCoinEntity);
        }
        // 执行添加
        int rows = videoCoinMapper.insert(videoCoinEntity);
        if (rows != 1) {
            throw new BaseException("新增视频币明细数据失败，服务器忙，请稍后再试！");
        }
    }

    /**
     * 支出的字段处理
     * @param videoCoinAddDTO
     * @param videoCoinEntity
     */
    private void handleExpendType(YxVideoCoinAddDTO videoCoinAddDTO, YxVideoCoinEntity videoCoinEntity) {
        // 从直播费用记录表中获取对应的信息保存到明细中
        YxLiveCostEntity yxLiveCostEntity = liveCostMapper.selectById(videoCoinAddDTO.getLiveCostId());
        videoCoinEntity.setShopId(yxLiveCostEntity.getShopId());
        videoCoinEntity.setTradingTime(yxLiveCostEntity.getExpenditureTime());
        // 如果详情为 '1' 进行违规扣除视频币的处理
        if (Integer.parseInt(videoCoinAddDTO.getDetail()) == 1) {
            //获取直播费用记录中的违规的视频币扣除数量
            int illegalExpend = yxLiveCostEntity.getIllegalExpend();
            double roundedValue = Math.round((double) illegalExpend * 100.0) / 100.0;
            String resultString = String.format("%.2f", roundedValue);
            videoCoinEntity.setAmount("-" + resultString);
            // 详情中时间部分的格式处理
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
            String dateString = dateFormat.format(yxLiveCostEntity.getExpenditureTime());
            videoCoinEntity.setDetail(VideoCoinMapper.VIDEO_COIN_DETAIL[Integer.parseInt(videoCoinAddDTO.getDetail())] + " " + dateString);
            // 否则正常进行直播结束后的视频币结算
        } else {
            // 获取直播费用记录中的直播结束的视频币扣除数量
            int expendVideoCoin = yxLiveCostEntity.getExpendVideoCoin();
            double roundedValue = Math.round((double) expendVideoCoin * 100.0) / 100.0;
            String resultString = String.format("%.2f", roundedValue);
            videoCoinEntity.setAmount("-" + resultString);
            // 详情中时间部分的格式处理
            String formattedTime = formatLiveCostTime(yxLiveCostEntity);
            videoCoinEntity.setDetail(VideoCoinMapper.VIDEO_COIN_DETAIL[Integer.parseInt(videoCoinAddDTO.getDetail())] + " " + formattedTime);
        }
        // 其余字段处理
        videoCoinEntity.setTransactionNum(IdWorkerUtils.generateTransactionNumber());
        videoCoinEntity.setRemark(yxLiveCostEntity.getRemark());
        // 从店铺中获取对应字段的信息
        YxLiveShopEntity yxLiveShopEntity = shopMapper.selectById(yxLiveCostEntity.getShopId());
        videoCoinEntity.setShopName(yxLiveShopEntity.getShopName());
        String merchantId = yxLiveShopEntity.getMerchantId();
        if (NumberUtils.isParsable(merchantId)) {
            videoCoinEntity.setShopkeeperId(Long.parseLong(merchantId));
        }
        videoCoinEntity.setShopkeeperName(yxLiveShopEntity.getMerchantName());
    }

    /**
     * 兑换的字段处理
     * @param videoCoinAddDTO
     * @param videoCoinEntity
     */
    private void handleRechargeType(YxVideoCoinAddDTO videoCoinAddDTO, YxVideoCoinEntity videoCoinEntity) {
        // 从兑换表中获取对应的信息保存到明细中
        YxVideoCoinExchangeEntity videoCoinExchangeEntity = videoCoinExchangeMapper.selectById(videoCoinAddDTO.getExchangeRulesId());
        videoCoinEntity.setShopId(videoCoinExchangeEntity.getExchangeShopId());
        videoCoinEntity.setShopName(videoCoinExchangeEntity.getExchangeShopName());
        videoCoinEntity.setTradingTime(videoCoinExchangeEntity.getExchangeTime());
        int exchangeVideoCoins = videoCoinExchangeEntity.getExchangeVideoCoins();
        // 明细表中的金额格式处理
        double roundedValue = Math.round((double) exchangeVideoCoins * 100.0) / 100.0;
        String resultString = String.format("%.2f", roundedValue);
        videoCoinEntity.setAmount("+" + resultString);
        videoCoinEntity.setDetail(VideoCoinMapper.VIDEO_COIN_DETAIL[Integer.parseInt(videoCoinAddDTO.getDetail())]);
        videoCoinEntity.setTransactionNum(IdWorkerUtils.generateTransactionNumber());
        videoCoinEntity.setRemark(videoCoinExchangeEntity.getRemark());
        // 从店铺中获取对应字段的信息
        YxLiveShopEntity yxLiveShopEntity = shopMapper.selectById(videoCoinExchangeEntity.getExchangeShopId());
        String merchantId = yxLiveShopEntity.getMerchantId();
        if (NumberUtils.isParsable(merchantId)) {
            videoCoinEntity.setShopkeeperId(Long.parseLong(merchantId));
        }
        videoCoinEntity.setShopkeeperName(yxLiveShopEntity.getMerchantName());
    }

    /**
     * 时间格式的处理
     * @param yxLiveCostEntity
     * @return
     */
    private String formatLiveCostTime(YxLiveCostEntity yxLiveCostEntity) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
        SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
        String startDate = dateFormat.format(yxLiveCostEntity.getStartTime());
        String endDate = dateFormat.format(yxLiveCostEntity.getEndTime());
        String startTime = timeFormat.format(yxLiveCostEntity.getStartTime());
        String endTime = timeFormat.format(yxLiveCostEntity.getEndTime());
        if (!startDate.equals(endDate)) {
            endDate = dateFormat.format(yxLiveCostEntity.getEndTime());
            return startDate + " " + startTime + "-" + endDate + " " + endTime;
        } else {
            return startDate + " " + startTime + "-" + endTime;
        }
    }

    /**
     * 获取视频币明细列表
     * @param dto
     * @return
     */
    @Override
    public PageVO<List<YxVideoCoinVO>> getVideoCoinList(YxVideoCoinQueryDTO dto) {
        Page<YxVideoCoinVO> page = new Page<>(dto.getCurrPage(), dto.getPageSize());
        List<YxVideoCoinVO> list = videoCoinMapper.getVideoCoinList(page, dto);
        Map<String, List<YxVideoCoinVO>> map = new HashMap<>();
        List<List<YxVideoCoinVO>> result = new ArrayList<>();
        for (YxVideoCoinVO vo : list) {
            String yearMonth = vo.getYearMonth();
            if (map.containsKey(yearMonth)) {
                map.get(yearMonth).add(vo);
            } else {
                List<YxVideoCoinVO> newList = new ArrayList<>();
                newList.add(vo);
                map.put(yearMonth, newList);

                result.add(newList);
            }
            double totalAmountIncrease = Double.parseDouble(vo.getTotalAmountIncrease());
            String totalAmountIncreaseString = String.format("%.2f", totalAmountIncrease);
            if (totalAmountIncrease > 0) {
                totalAmountIncreaseString = "+" + totalAmountIncreaseString;
            }

            vo.setTotalAmountIncrease(totalAmountIncreaseString);
            double totalAmountReduce = Double.parseDouble(vo.getTotalAmountReduce());
            String totalAmountReduceString = String.format("%.2f", totalAmountReduce);
            if (totalAmountReduce > 0) {
                totalAmountReduceString = "-" + totalAmountReduceString;
            }
            vo.setTotalAmountReduce(totalAmountReduceString);
        }
        for (List<YxVideoCoinVO> newList : result) {
            Collections.sort(newList, Comparator.comparing(YxVideoCoinVO::getTradingTime).reversed());
        }
        Collections.reverse(result);
        return PageUtils.get(page, result);
    }

    /**
     * 获取视频币明细列表后台
     * @param dto
     * @return
     */
    @Override
    public PageVO<YxVideoCoinVO> getVideoCoinListBackend(VideoCoinQueryDTO dto) {
        Page<YxVideoCoinVO> page = new Page<>(dto.getCurrPage(), dto.getPageSize());
        List<YxVideoCoinVO> list = videoCoinMapper.getVideoCoinListBackend(page, dto);
        return PageUtils.get(page, list);
    }

    /**
     * 根据ID获取视频币明细详情
     * @param videoCoinId
     * @return
     */
    @Override
    public YxVideoCoinVO getVideoCoinById(Long videoCoinId) {
        YxVideoCoinEntity videoCoinEntity = videoCoinMapper.selectById(videoCoinId);
        YxVideoCoinVO vo = new YxVideoCoinVO();
        BeanUtil.copyProperties(videoCoinEntity, vo);
        return vo;
    }

    /**
     * 添加直播中违规扣除视频币费用记录
     * @param liveCostAddDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addIllegalCostDuringLive(YxLiveCostAddDTO liveCostAddDTO) {
        if (liveCostAddDTO.getPunishId() == null && liveCostAddDTO.getLiveId() == null) {
            throw new BaseException("违规ID与直播ID不能为空");
        }
        YxLiveCostEntity liveCost = new YxLiveCostEntity();
        BeanUtils.copyProperties(liveCostAddDTO, liveCost);
        // 根据违规ID查询违规记录
        YxLiveShopPunishEntity shopPunishEntity = liveShopPunishMapper.selectById(liveCostAddDTO.getPunishId());
        if (shopPunishEntity == null) {
            throw new BaseException("违规记录信息不存在");
        }
        if (shopPunishEntity.getPunishType() != 0) {
            throw new BaseException("该违规记录不是视频币扣除类型");
        }
        // 根据直播ID查询直播记录
        YxLiveAddressEntity liveAddressEntity = liveAddressMapper.selectById(liveCostAddDTO.getLiveId());
        if (liveAddressEntity == null) {
            throw new BaseException("直播地址信息不存在");
        }
        // 从店铺表中获取视频币余额,判断够不够扣除
        YxLiveShopEntity shopEntity = shopMapper.selectById(liveAddressEntity.getLiveShopId());
        BigDecimal currentCoin = shopEntity.getLiveCoin();
        BigDecimal illegalExpend = BigDecimal.valueOf(shopPunishEntity.getPunishQuantity());
        if (currentCoin.compareTo(illegalExpend) < 0) {
            throw new BaseException("视频币余额不足，无法扣除违规视频币");
        }
        // 更新扣除后店铺表中的视频币余额
        shopEntity.setLiveCoin(currentCoin.subtract(illegalExpend));
        shopEntity.setUpdateTime(new Date());
        int rows = shopMapper.updateById(shopEntity);
        if (rows != 1) {
            throw new BaseException("视频币扣除失败，服务器忙，请稍后尝试！");
        }
        // 添加直播费用表中的违规扣除记录
        liveCost.setIllegalExpend(illegalExpend.intValue());
        liveCost.setExpenditureTime(shopPunishEntity.getCreateTime());
        liveCost.setShopId(liveAddressEntity.getLiveShopId());
        rows = liveCostMapper.insert(liveCost);
        if (rows != 1) {
            throw new BaseException("新增违规视频币支出记录数据失败，服务器忙，请稍后再试！");
        }
        // 添加违规扣除视频币的明细
        YxVideoCoinAddDTO addDTO = new YxVideoCoinAddDTO();
        addDTO.setLiveCostId(liveCost.getLiveCostId());
        addDTO.setDetail("1");
        addDTO.setType(CommonConstant.ZERO);
        addVideoCoin(addDTO);
    }


    /**
     * 添加直播完费用记录
     * @param liveCostAddDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addLiveCost(YxLiveCostAddDTO liveCostAddDTO) {
        if (liveCostAddDTO.getLiveId() == null) {
            throw new BaseException("直播ID不能为空");
        }
        YxLiveCostEntity liveCost = new YxLiveCostEntity();
        BeanUtils.copyProperties(liveCostAddDTO, liveCost);
        // 根据直播ID查询直播记录
        YxLiveAddressEntity liveAddressEntity = liveAddressMapper.selectById(liveCostAddDTO.getLiveId());
        if (liveAddressEntity == null) {
            throw new BaseException("直播地址信息不存在");
        }
        // 根据直播时间计算总时长(分钟)
        liveCost.setStartTime(BaseDateTime.getDate(liveAddressEntity.getLiveStartTime()/1000));
        liveCost.setEndTime(BaseDateTime.getDate(liveAddressEntity.getLiveEndTime()/1000));
        long startTime = liveAddressEntity.getLiveStartTime();
        long endTime = liveAddressEntity.getLiveEndTime();
        long durationMillis;
        if (endTime > startTime) {
            durationMillis = endTime - startTime;
        } else {
            durationMillis = startTime - endTime;
        }
        String minutes = String.valueOf(durationMillis / (60 * 1000));
        liveCost.setTotalTime(minutes);
        // 添加直播费用表中的直播结束后视频币扣除记录
        liveCost.setExpendVideoCoin(liveAddressEntity.getLiveFees());
        liveCost.setExpenditureTime(BaseDateTime.getDate(liveAddressEntity.getLiveEndTime()/1000));
        liveCost.setShopId(liveAddressEntity.getLiveShopId());
        liveCost.setRemark(liveCostAddDTO.getRemark());
        int rows = liveCostMapper.insert(liveCost);
        if (rows != 1) {
            throw new BaseException("新增直播视频币支出记录数据失败，服务器忙，请稍后再试！");
        }
        // 更新扣除后店铺表中的视频币余额
        YxLiveShopEntity shopEntity = shopMapper.selectById(liveAddressEntity.getLiveShopId());
        AssertUtil.isNotNull(shopEntity, ErrorCodeEnum.OBJ_EMPTY);
        if (BigDecimal.valueOf(liveCost.getExpendVideoCoin()).compareTo(shopEntity.getLiveCoin()) > 0) {
            shopEntity.setLiveCoin(BigDecimal.valueOf(CommonConstant.ZERO));
        }else {
            shopEntity.setLiveCoin(shopEntity.getLiveCoin().subtract(BigDecimal.valueOf(liveCost.getExpendVideoCoin())));
        }
        shopEntity.setUpdateTime(new Date());
        rows = shopMapper.updateById(shopEntity);
        if (rows != 1) {
            throw new BaseException("视频币支出失败，服务器忙，请稍后尝试！");
        }
        // 添加直播结束扣除视频币的明细
        YxVideoCoinAddDTO addDTO = new YxVideoCoinAddDTO();
        addDTO.setLiveCostId(liveCost.getLiveCostId());
        addDTO.setDetail("0");
        addDTO.setType(CommonConstant.ZERO);
        addVideoCoin(addDTO);
    }

}
